<?php
/**
* 虎绿林WAP6 读取用户信息
*/
class userinfo implements ArrayAccess {
protected static $data; //用户数据缓存

protected static $name; //用户名到uid对应关系的缓存
protected static $info; //用户配置数据缓存
protected $uid; //当前用户
  
/**
* 连接数据库
* 参数：
* $read_only  如果为true，打开一个只读的数据库连接，只允许查询；否则打开一个可读可写的连接。实现分布式应用的读写分离。
*/
protected static function conn($read_only=false)
{
return db::conn('user',$read_only);
}
  
/*
* 检查用户名是否有效
* 用户名只允许汉字、字母、数字、下划线(_)和减号(-)。
*/
public static function checkName($name) {
if($name=='') throw new userexception('用户名不能为空。',10);
if(strlen(mb_convert_encoding($name,'gbk','utf-8'))>16) throw new userexception("用户名 \"$name\" 过长。用户名最长只允许16个英文字母或8个汉字（16字节）。",13);
if(!str::匹配汉字($name,'A-Za-z0-9_\\-')) throw new userexception("用户名 \"$name\" 无效。只允许汉字、字母、数字、下划线(_)和减号(-)。",11);
return TRUE;
 }
  
/*
* 检查uid是否有效
*/
public static function checkUid($x_uid) {
$x_uid=(string)$x_uid;
$uid=(int)$x_uid;
if($x_uid!==(string)$uid) throw new userexception("用户ID \"$x_uid\" 无效。用户ID必须是一个正整数。",14);
if($uid<1) throw new userexception("用户ID \"$x_uid\" 错误。用户ID不能小于1。",15);
return TRUE;
 }
  
/*取得用户的info数据*/
public function getinfo($index=null)
{
$set=self::$info[$this->uid];
if($set===NULL) {
static $rs;
 if(!$rs) {
$db=self::conn(true);
$rs=$db->prepare('SELECT `info` FROM `'.DB_A.'user` WHERE `uid`=?');
 }
if(!$rs || !$rs->execute(array($this->uid))) return FALSE;
$data=$rs->fetch(db::ass);
self::parseinfo($this->uid,$data['info']);
$set=self::$info[$this->uid];
}
if($index===null) return $set;
$index=explode('.',$index);
foreach($index as $key)
 {$set=$set[$key];}
return $set;
}
    
/*解析用户的info数据*/
protected static function parseinfo($uid,$info) {
$info=unserialize($info);
if($info===NULL) $info=array();

self::$info[$uid]=$info;
 }
  
/**
* 取得指定用户名的信息，并存储在属性内。之后你可以通过$obj->uid等属性访问用户信息。
* 参数：
* $name 用户名

* $getinfo=FALSE 是否同时取得info信息
*    （为了优化数据库查询，减少不必要的查询。只有在你需要它时设置它为true）
*     若$getinfo为假，则当访问info信息时将自动重新获取。
* 返回值：成功返回TRUE，失败（用户名不存在）返回FALSE
*/
public function name($name,$getinfo=false) {
$this->uid=NULL;

try {
self::checkname($name);
  } catch(userexception $ERR) {
return FALSE;
  }
$uid=self::$name[$name];
if($uid!==NULL) {
$this->uid=$uid;
return $uid!==FALSE ? TRUE : FALSE;
 }
static $rs,$x_getinfo;
if(!$rs || $getinfo!=$x_getinfo) {
$db=self::conn(true);
$rs=$db->prepare('SELECT `uid`,`name`,`regtime`,`acctime`'.($getinfo ? ',`info`' : '').' FROM `'.DB_A.'user` WHERE `name`=?');
$x_getinfo=$getinfo;
  }
if(!$rs || !$rs->execute(array($name))) return FALSE;
$data=$rs->fetch(db::ass);
if(!isset($data['uid'])) {
self::$name[$name]=FALSE;
return FALSE;

 }
$this->uid=$data['uid'];

if($getinfo) {
self::parseinfo($this->uid,$data['info']);
unset($data['info']);
 }
self::$data[$this->uid]=$data;

self::$name[$data['name']]=$this->uid;
return TRUE;
 }
  
/**
* 取得指定uid的信息，并存储在属性内。之后你可以通过$obj->name等属性访问用户信息。
* 参数：
* $uid 用户ID

* $getinfo=FALSE 是否同时取得info信息
*    （为了优化数据库查询，减少不必要的查询。只有在你需要它时设置它为trun）
*     若$getinfo为假，则当访问info信息时将自动重新获取。


* 返回值：成功返回TRUE，失败（uid不存在）返回FALSE
*/
public function uid($uid,$getinfo=false) {
$this->uid=NULL;
try {
self::checkuid($uid);
  } catch(userexception $ERR) {
return FALSE;
  }
$data=self::$data[$uid];
if($data!==NULL) {
$this->uid=$uid;
return $data!==FALSE ? TRUE : FALSE;
 }
static $rs,$x_getinfo;
if(!$rs || $getinfo!=$x_getinfo) {
$db=self::conn(true);
$rs=$db->prepare('SELECT `uid`,`name`,`regtime`,`acctime`'.($getinfo ? ',`info`' : '').' FROM `'.DB_A.'user` WHERE `uid`=?');
$x_getinfo=$getinfo;
  }
if(!$rs || !$rs->execute(array($uid))) return FALSE;
$data=$rs->fetch(db::ass);
if(!isset($data['uid'])) {
self::$data[$uid]=FALSE;
return FALSE;

  }
$this->uid=$data['uid'];
if($getinfo) {
self::parseinfo($this->uid,$data['info']);
unset($data['info']);
 }
self::$data[$this->uid]=$data;

self::$name[$data['name']]=$this->uid;
return TRUE;
 }
  
public function __isset($name)
{
 return isset(self::$data[$this->uid][$name]);
}
public function __get($name)
{
 return self::$data[$this->uid][$name];
}
public function __set($name,$value)
{
throw new userexception('不能从类外部修改用户信息',503);
}
public function __unset($name)
{
throw new pageexception('不能从类外部删除用户信息',503);
}
/*下面是ArrayAccess接口*/
public function offsetExists($name)
{
return isset(self::$data[$this->uid][$name]);
}
public function offsetGet($name)
{
return self::$data[$this->uid][$name];
}
public function offsetSet($name,$value)
{
throw new pageexception('不能从类外部修改用户信息',503);
}
public function offsetUnset($name)
{
throw new pageexception('不能从类外部删除用户信息',503);
}
  
/*class end*/
}